package com.ptc.ims.server;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.ptc.ims.shared.InventoryException;
import com.ptc.ims.shared.Product;

public class InventoryDAO {
	private Map<String, Product> stock;

	// thread-safe singleton
	private static final InventoryDAO instance = new InventoryDAO();
	private InventoryDAO() {
		initData();
	}

	public static synchronized InventoryDAO getInstance() {
		return instance;
	}

	/**
	 * @return An ArrayList of Products, that is a shallow copy of the 
	 * actual data collection.
	 * @throws InventoryException if the list retrieval is unsuccessful
	 */
	public List<Product> getItems() throws InventoryException {
		try {
			Collection<Product> stockRef = stock.values();
			ArrayList<Product> itemListCopy = new ArrayList<Product>();
			for(Product item : stockRef) {
				itemListCopy.add(new Product(item.getId(), item.getName(), item.getPrice()));
			}
			Thread.sleep(300);// to simulate network latency
			return itemListCopy;
		} catch (Exception e) {
			e.printStackTrace();
			throw new InventoryException(e.getMessage());
		}
	}

	/**
	 * Edit an item
	 * @param itemId the ID of the item to be edited 
	 * @param newValues the new values to set on the item
	 * @throws InventoryException if the item does not exist
	 */
	public void editItem(String itemId, Product newValues) throws InventoryException {
		if(itemId==null || "".equals(itemId)) {
			throw new InventoryException("Invalid item ID.");
		}
		if(stock.containsKey(itemId)) {
			stock.put(itemId, newValues);
		} else {
			throw new InventoryException("Item ID does not exist.", newValues);
		}
	}

	public void addItem(String itemId, Product newItem) throws InventoryException {
		if(stock.containsKey(itemId)) {
			throw new InventoryException("Item ID already exists.", newItem);
		} else {
			stock.put(itemId, newItem);
		}
	}

	public void deleteItem(String itemId) throws InventoryException {
		if(stock.containsKey(itemId)) {
			stock.remove(itemId);
		} else {
			throw new InventoryException("Item ID does not exist.", new Product(itemId, null, null));
		}
	}

	public String generateID() {
		String newId = "00" + String.valueOf(getRandomPrice()).replaceAll("\\.\\d*", "ITEM");
		if(stock.containsKey(newId)) {
			return generateID();
		} else {
			return newId; 
		}
	}

	// generates dummy data
	private void initData() {
		stock = new LinkedHashMap<String, Product>(0);
		for(String name : dummyStockList) {
			String itemId = generateID();
			Product item = new Product(itemId, name, getRandomPrice());
			stock.put(itemId, item);
		}
	}

	private Double getRandomPrice() {
		return (Math.random() * 199) + 6;
	}

	private String[] dummyStockList = {
		"Wow Ulam",
		"Sarsarap",
		"Datu Puti Vinegar",
		"Jimm's 5-in-1 Coffee"
	};
}